[HVM] Shadow: avoid xen crash if guest uses special memory for pagetables
authorTim Deegan <Tim.Deegan@xensource.com>
Thu, 5 Jul 2007 13:46:13 +0000 (14:46 +0100)
committerTim Deegan <Tim.Deegan@xensource.com>
Thu, 5 Jul 2007 13:46:13 +0000 (14:46 +0100)
(just crash the guest and don't do any more PTE propagations).
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
xen/arch/x86/mm/shadow/common.c
xen/arch/x86/mm/shadow/multi.c

index eb015b7a1b97ff23bf0c2c4da5bb429fc1dc5e24..7e53c23a3657e1e39b099b8f1a5b79ecc50e8225 100644 (file)
@@ -506,7 +506,9 @@ void shadow_promote(struct vcpu *v, mfn_t gmfn, unsigned int type)
     ASSERT(mfn_valid(gmfn));
 
     /* We should never try to promote a gmfn that has writeable mappings */
-    ASSERT(sh_remove_write_access(v, gmfn, 0, 0) == 0);
+    ASSERT((page->u.inuse.type_info & PGT_type_mask) != PGT_writable_page
+           || (page->u.inuse.type_info & PGT_count_mask) == 0
+           || v->domain->is_shutting_down);
 
     /* Is the page already shadowed? */
     if ( !test_and_set_bit(_PGC_page_table, &page->count_info) )
@@ -1850,11 +1852,12 @@ int sh_remove_write_access(struct vcpu *v, mfn_t gmfn,
     perfc_incr(shadow_writeable_bf);
     hash_foreach(v, callback_mask, callbacks, gmfn);
 
-    /* If that didn't catch the mapping, something is very wrong */
+    /* If that didn't catch the mapping, then there's some non-pagetable
+     * mapping -- ioreq page, grant mapping, &c. */
     if ( (mfn_to_page(gmfn)->u.inuse.type_info & PGT_count_mask) != 0 )
     {
-        SHADOW_ERROR("can't find all writeable mappings of mfn %lx: "
-                      "%lu left\n", mfn_x(gmfn),
+        SHADOW_ERROR("can't remove write access to mfn %lx: guest has "
+                      "%lu special-use mappings of it\n", mfn_x(gmfn),
                       (mfn_to_page(gmfn)->u.inuse.type_info&PGT_count_mask));
         domain_crash(v->domain);
     }
index 962caa05ee81f0acc8e43ef638d407ad8f0ba139..6e2f7b92b27c8a1a2f3c621728305f200734a473 100644 (file)
@@ -2719,10 +2719,21 @@ static int sh_page_fault(struct vcpu *v,
                    
     if ( guest_walk_tables(v, va, &gw, 1) != 0 )
     {
-        SHADOW_PRINTK("malformed guest pagetable!");
+        SHADOW_PRINTK("malformed guest pagetable\n");
         print_gw(&gw);
     }
 
+    /* It's possible that the guest has put pagetables in memory that it has 
+     * already used for some special purpose (ioreq pages, or granted pages).
+     * If that happens we'll have killed the guest already but it's still not 
+     * safe to propagate entries out of the guest PT so get out now. */
+    if ( unlikely(d->is_shutting_down) )
+    {
+        SHADOW_PRINTK("guest is shutting down\n");
+        shadow_unlock(d);
+        return 0;
+    }
+
     sh_audit_gw(v, &gw);
 
     // We do not look at the gw->l1e, as that will not exist for superpages.